﻿using System;
using System.IO;
using System.Net.Sockets;
using System.Threading;
using System.Windows.Forms;

namespace QAQ
{
    class SocServer
    {
        static TcpListener listener = null;
        static GCPacket mGCPacket = null;

        const int LIMIT = 3; //1 concurrent clients
        Thread[] mThreads = new Thread[LIMIT];


        public SocServer(GCPacket GCP, int Port)
        {
            listener = new TcpListener(Port);
            listener.Start();
            mGCPacket = GCP;

            for (int i = 0; i < LIMIT; i++)
            {
                mThreads[i] = new Thread(new ThreadStart(Service));
                mThreads[i].Start();
            }
        }
        public void Dispose()
        {
            listener.Stop();
            for (int i = 0; i < LIMIT; i++)
            {
                mThreads[i].Interrupt();
                mThreads[i].Abort();
            }
        }


        public static void WritingThread(object o)
        {
            StreamWriter sw = new StreamWriter((Stream)o);

            sw.AutoFlush = true; // enable automatic flushing
            try
            {

                for (; ; )
                {
                    if (false == mGCPacket.sent)
                    {
                        if (false == mGCPacket.isValid())
                        {
                            throw new ArgumentException("Sending void packet");
                        }
                        //TODO:try catch to imform main thread and close the listen threads
                        sw.WriteLine("HEY"); //TODO: HEY CLIENT!

                        sw.WriteLine(mGCPacket.id.ToString());
                        sw.WriteLine(mGCPacket.pw);
                        mGCPacket.sent = true;
                    }
                    if (true == Form1.GG3be0)
                    {
                        Form1.GG3be0 = false;
                        sw.WriteLine("GG3BE0");
                    }
                    System.Threading.Thread.Sleep(100);
                }
            }
            catch (Exception excp)
            {
                sw.Close();
            }
        }

        public static void ReadingThread(object o)
        {
            StreamReader sr = new StreamReader((Stream)o);

            try
            {
                for (; ; )
                {
                    switch (sr.ReadLine())
                    {
                        case "G":
                            if (true == mGCPacket.isValid())
                            {
                                mGCPacket.sent = false;
                            }
                            break;
                        case "BAD":
                            Form1.mBadass = true;
                            break;
                        case "GO!":
                            Form1.GoNow = true;
                            break;
                        default:
                            break;
                    }

                }
            }
            catch (Exception exc)
            {
                sr.Close();
            }
        }


        public static void Service()
        {
            for (; ; )
            {
                Socket soc;
                try
                {
                    soc = listener.AcceptSocket();
                }
                catch (Exception e)
                {
                    return;
                }
                //soc.SetSocketOption(SocketOptionLevel.Socket,
                //        SocketOptionName.ReceiveTimeout,10000);
                try
                {
                    Stream s = new NetworkStream(soc);


                    Thread wThread = new Thread(new ParameterizedThreadStart(WritingThread));
                    Thread rThread = new Thread(new ParameterizedThreadStart(ReadingThread));
                    wThread.IsBackground = true;
                    rThread.IsBackground = true;
                    wThread.Start(s);
                    rThread.Start(s);

                    wThread.Join();
                    rThread.Join();
                }
                catch (Exception e)
                {
                    //      MessageBox.Show(e.ToString());
                }
                try
                {
                    soc.Close();
                }
                catch (Exception)
                {
                    
                    throw;
                }
                
            }
        }
    }
}
